# -*- coding: iso-8859-1 -*-
#
#    Malvinas Argentinas Messenger is free software; you can redistribute
#    it and/or modify it under the terms of the GNU General Public License
#    as published by the Free Software Foundation; either version 2 of the
#    License, or (at your option) any later version.
#
#    Malvinas Argentinas Messenger is distributed in the hope that it will be
#    useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with Malvinas Argentinas Messenger; if not, write to the Free
#    Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
#    MA  02110-1301  USA

import socket, select, threading
from time import sleep, strftime, localtime
from utils import strMD5
from string import split, rstrip
import datetime

class MsgServer(threading.Thread):
	def __init__(self, ui):
		self.ui = ui
		threading.Thread.__init__ (self)
		self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
		self.server.bind(('localhost', 6214))
		self.server.listen(5)
		self.desc = [self.server]

	def __getstate__(self):
		return

	def accept_new_connection(self):
		try:
			self.server.settimeout(.1)
			self.newsock, (self.remhost, self.remport) = self.server.accept()
			self.ui.debug("Se ha conectado %s:%s" % (str(self.remhost), str(self.remport)))
			self.desc.append(self.newsock)
		except:
			#self.ui.debug("No hubo conexion")
			pass

	def broadcast(self, msg, sock):
			self.host, self.port = sock.getpeername()
			msg = "[%s:%s]: %s" % (str(self.host), str(self.port), str(msg))
			for self.destsock in self.desc:
				if self.destsock != sock and self.destsock != self.server and self.destsock != sys.stdin:
					self.destsock.send(msg)

	def get_msg(self, sock):
		try:
			#self.ui.debug("Intentando recibir mensaje")
			sock.settimeout(.1)
			self.msg = sock.recv(1024)
			#self.ui.debug("Recibido mensaje")
			return self.msg
		except:
			self.host, self.port = sock.getpeername()
			self.ui.debug("[%s:%s] ha salido." % (str(self.host), str(self.port)))
			self.desc.remove(sock)
			sleep(5)
			return None

	def run(self):
		autenticados = []
		while 1:
			self.accept_new_connection()
			#lock.release()
			(self.sread, self.swrite, self.sexc) = select.select(self.desc, [], [])
			for sock in self.sread:
				if sock != self.server:
					try:
						sock.settimeout(.1)
						gotMsg = self.get_msg(sock)
					except:
						gotMsg = ""
					if (gotMsg is not None) and \
					(gotMsg == strMD5(self.ui.account + self.ui.password)) and \
					(sock is not None) and \
					(sock not in autenticados):
						self.ui.debug("ServerAndino >> " + gotMsg)
						autenticados.append(sock)
						sock.send('OK')
						self.ui.debug("ServerAndino >> HandShakeOK!!")
					elif sock is not None:
						tipo = gotMsg[:3]
						if tipo == "NLN" and self.ui.listaContactosIniciada == True:
							m = split(gotMsg, " ")
							#account = m[1]
							nick = self.ui.controller.getContact(self.ui.account, m[1]).nick
							self.ui.debug(nick + " cambio de estado a " + m[2])
							self.ui.buildList()

						elif tipo == "JOI":
							m = split(gotMsg, " ")
							passport = m[1]
							mensajes = self.ui.controller.getPendingMsg(self.ui.account, passport)
							n = self.ui.padArray.hasPass(passport)
							if n == -1:
								self.ui.debug("Error en msgServer - JOI")
								return
							#self.ui.debug("Entre en JOI")
							self.ui.controller.sendPendingMsg(self.ui.account, passport)
							ctime = strftime(self.ui.controller.getConfig(self.ui.account)['timestamp_format'], localtime())
							for e in mensajes:
								self.ui.controller.debug(str(e))
								#self.ui.debug("mensaje enviado: " + e[1] + ". En ventana: " + str(n-1))
								self.ui.padArray.wins[n-1].ventana.addstr('\n', self.ui.COLORS.WHITE)
								self.ui.padArray.wins[n-1].ventana.addstr(e[0], self.ui.COLORS.WHITE)
								self.ui.padArray.wins[n-1].ventana.addstr(" >> ", self.ui.COLORS.WHITE)
								self.ui.padArray.wins[n-1].ventana.addstr(e[1], self.ui.COLORS.BLACK_R)
							if self.ui.padArray.wins[n-1].waitingJoi:
								self.ui.padArray.wins[n-1].unset_waitingJoi()
							if self.ui.padArray.wins[n-1].ventana.scroll > 0:
								self.ui.padArray.wins[n-1].ventana.scroll -= 1
							self.ui.refreshScr()

						elif tipo == "WRI":
							# TODO: Probar cuando no existe conversacion activa.
							m = split(gotMsg, " ")
							passport = m[1]
							n = self.ui.padArray.hasPass(passport)
							if n == -1:
								self.ui.debug("Ver en msgServer - WRI")
								return
							self.ui.padArray.wins[n-1].set_typingFlag()
							self.ui.padArray.wins[n-1].time_last_typing = datetime.datetime.now()
							self.ui.refreshScr()
							# Largo un hilo para que a los 10 segundos sin recibir typing saque la marca
							t = threading.Thread(target=self.ui.desmarcarTyping, args=(passport, ))
							t.setDaemon(True)
							t.start()

						elif tipo == "MSG":
							m = split(gotMsg, " ")
							ctime = strftime(self.ui.controller.getConfig(self.ui.account)['timestamp_format'], localtime())
							strMensaje = ""
							for strm in m[2:]:
								strMensaje = strMensaje + strm + " "
							rstrip(strMensaje)
							# Busco ventana de conversacion
							n = self.ui.padArray.hasPass(m[1])
							nick = self.ui.controller.getContact(self.ui.account, m[1]).nick
							if n <> -1:
								idTab = n - 1						
							# I open a new tab
							else:
								self.ui.padArray.newWin(nick, m[1])
								idTab = self.ui.padArray.size() - 1
							self.ui.padArray.wins[idTab].ventana.addstr('\n', self.ui.COLORS.WHITE)
							self.ui.padArray.wins[idTab].ventana.addstr(ctime, self.ui.COLORS.WHITE)
							self.ui.padArray.wins[idTab].ventana.addstr(" << ", self.ui.COLORS.BLUE_R)
							self.ui.padArray.wins[idTab].ventana.addstr(strMensaje, self.ui.COLORS.WHITE_R)
							if idTab <> self.ui.padArray.idactive: self.ui.padArray.wins[idTab].set_newMsgFlag()
							self.ui.refreshScr()
						else:
							self.ui.info("ServerAndino >> " + gotMsg)

					elif sock not in autenticados:
						self.ui.debug("Alguien se conecto sin autenticacion correcta. Cerrando Socket")
						try:
							#FIXME
							#sock.shutdown(1)
							#sock.close()
							#self.sread.remove(sock)
							pass
						except:
							#Bad File descriptor
							pass

					else:
						if self.ui.self.listaContactosIniciada == True:
							self.ui.debug("Mensaje del Servidor Andino: " + gotMsg)
						#self.broadcast(newMsg, sock)
